home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / utility / uwserver.zip / uwserver.tar / server / openpty.c < prev    next >
C/C++ Source or Header  |  1991-01-25  |  4KB  |  151 lines

  1. /*
  2.  *    openpty - open a pseudo-terminal
  3.  *
  4.  * The first time that the routine is called, the device directory is
  5.  * searched and a list of all candidate pseudo-terminals is compiled.
  6.  * Candidates are defined to be those entries in "/dev" whose names
  7.  * (1) are the same length as PTY_PROTO and (2) start with the
  8.  * initial string PTY_PREFIX.  Further, the master and slave sides
  9.  * must both exist.
  10.  *
  11.  * openpty() attempts to find an unused pseudo-terminal from the list
  12.  * of candidates.  If one is found, the master and slave sides are
  13.  * opened and the file descriptors and names of these two devices are
  14.  * returned in a "ptydesc" structure.  (The address of this structure
  15.  * is supplied by the caller.  Zero is returned if openpty() was
  16.  * successful, -1 is returned if no pty could be found.
  17.  */
  18.  
  19. #include <sys/types.h>
  20. #include <sys/dir.h>
  21. #include <fcntl.h>
  22. #include <strings.h>
  23. #include "openpty.h"
  24.  
  25. #define    DEV_DIR        "/dev"        /* directory where devices live */
  26. #define    PT_INDEX    (sizeof DEV_DIR)    /* location of 'p' in "pty" */
  27.  
  28. #define    PTY_PROTO    "ptyp0"        /* prototype for pty names */
  29. #define    PTY_PREFIX    "pty"        /* prefix required for name of pty */
  30.  
  31. struct ptyinfo {
  32.     struct ptyinfo    *pi_next;
  33.     char        *pi_pty;
  34.     char        *pi_tty;
  35. };
  36.  
  37. static struct ptyinfo *ptylist;
  38.  
  39. extern char *malloc();
  40.  
  41. static
  42. char *
  43. devname(name)
  44. char *name;
  45. {
  46.     register char *fullname;
  47.  
  48.     /*
  49.      * Construct the full name of a device in DEV_DIR.  Returns
  50.      * NULL if it failed (because malloc() failed).
  51.      */
  52.  
  53.     fullname = malloc((unsigned)(sizeof DEV_DIR + 1 + strlen(name)));
  54.     if (fullname != NULL) {
  55.         (void)strcpy(fullname, DEV_DIR);
  56.         (void)strcat(fullname, "/");
  57.         (void)strcat(fullname, name);
  58.     }
  59.     return(fullname);
  60. }
  61.  
  62. static
  63. isapty(dp)
  64. struct direct *dp;
  65. {
  66.     static struct ptyinfo *pi;
  67.  
  68.     /*
  69.      * We don't care about the gory details of the directory entry.
  70.      * Instead, what we really want is an array of pointers to
  71.      * device names (with DEV_DIR prepended).  Therefore, we create
  72.      * this array ourselves and tell scandir() to ignore every
  73.      * directory entry.
  74.      *
  75.      * If malloc() fails, the current directory entry is ignored.
  76.      */
  77.     if (pi == NULL) {
  78.         pi = (struct ptyinfo *)malloc((unsigned)sizeof *pi);
  79.         if (pi == NULL)
  80.             return(0);
  81.     }
  82.  
  83.     if (strlen(dp->d_name) == sizeof PTY_PROTO - 1 &&
  84.         strncmp(dp->d_name, PTY_PREFIX, sizeof PTY_PREFIX - 1) == 0) {
  85.         pi->pi_pty = devname(dp->d_name);
  86.         if (pi->pi_pty == NULL)
  87.             return(0);
  88.         pi->pi_tty = malloc((unsigned)(strlen(pi->pi_pty) + 1));
  89.         if (pi->pi_tty == NULL) {
  90.             free(pi->pi_pty);
  91.             return(0);
  92.         }
  93.         (void)strcpy(pi->pi_tty, pi->pi_pty);
  94.         pi->pi_tty[PT_INDEX] = 't';
  95.         if (access(pi->pi_pty, 0) == 0 && access(pi->pi_tty, 0) == 0) {
  96.             pi->pi_next = ptylist;
  97.             ptylist = pi;
  98.             pi = NULL;
  99.         } else {
  100.             free(pi->pi_pty);
  101.             free(pi->pi_tty);
  102.         }
  103.     }
  104.     return(0);
  105. }
  106.  
  107. openpty(pt)
  108. struct ptydesc *pt;
  109. {
  110.     register struct ptyinfo *pi;
  111.     static int fail;
  112.     auto struct direct **dirlist;
  113.     extern char *re_comp();
  114.     extern int alphasort();
  115.  
  116.     /*
  117.      * If scandir() fails or no possible pty's are found, then "fail"
  118.      * is set non-zero.  If "fail" is non-zero then the routine bombs
  119.      * out immediately.  Otherwise, the list of candidates is examined
  120.      * starting with the entry following the last one chosen.
  121.      */
  122.     if (fail)
  123.         return(-1);
  124.  
  125.     if (!ptylist) {        /* first time */
  126.         if (scandir(DEV_DIR, &dirlist, isapty, alphasort) < 0 ||
  127.             ptylist == NULL) {
  128.             fail = 1;
  129.             return(-1);
  130.         }
  131.         for (pi=ptylist; pi->pi_next; pi=pi->pi_next)
  132.             ;
  133.         pi->pi_next = ptylist;    /* make the list circular */
  134.     }
  135.  
  136.     pi = ptylist;
  137.     do {
  138.         if ((pt->pt_pfd = open(pi->pi_pty, O_RDWR)) >= 0) {
  139.             if ((pt->pt_tfd = open(pi->pi_tty, O_RDWR)) >= 0) {
  140.                 ptylist = pi->pi_next;
  141.                 pt->pt_pname = pi->pi_pty;
  142.                 pt->pt_tname = pi->pi_tty;
  143.                 return(0);
  144.             } else
  145.                 (void)close(pt->pt_pfd);
  146.         }
  147.         pi = pi->pi_next;
  148.     } while (pi != ptylist);
  149.     return(-1);
  150. }
  151.